﻿using System;
using System.Text.RegularExpressions;

namespace Quotation
{
    /// <summary>
    /// 表示时间
    /// </summary>
    public struct Time : IComparable<Time>
    {
        const string pattern = @"^([01]?\d|2[0-3]):([0-5]\d)$";

        public Time(int hour, int minute)
        {
            if (hour < 0 || hour > 23)
                throw new ArgumentOutOfRangeException();
            if (minute < 0 || minute > 59)
                throw new ArgumentOutOfRangeException();

            _hour = hour;
            _minute = minute;
            _second = 0;
        }
        public Time(int hour, int minute, int second)
            : this(hour, minute)
        {
            if (second < 0 || second > 59)
                throw new ArgumentOutOfRangeException();
            _second = second;
        }
        public Time(DateTime dateTime)
        {
            _hour = dateTime.Hour;
            _minute = dateTime.Minute;
            _second = dateTime.Second;
        }

        private int _hour;
        /// <summary>
        /// 小时部分
        /// </summary>
        public int Hour { get { return _hour; } }

        private int _minute;
        /// <summary>
        /// 分钟部分
        /// </summary>
        public int Minute { get { return _minute; } }

        private int _second;
        /// <summary>
        /// 秒
        /// </summary>
        public int Second { get { return _second; } }

        public override bool Equals(object obj)
        {
            if (obj is Time)
            {
                return this == (Time)obj;
            }
            else
            {
                return false;
            }
        }
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
        public override string ToString()
        {
            return string.Format("{0:00}:{1:00}:{2:00}", Hour, Minute, Second);
        }
        public string ToShortString()
        {
            return string.Format("{0:00}:{1:00}", Hour, Minute);
        }

        public int ToHMM()
        {
            return Hour * 100 + Minute;
        }
        public int ToHMMss()
        {
            return Hour * 10000 + Minute * 100 + Second;
        }


        public static Time FromHMM(string timeStr)
        {
            int time;
            if (int.TryParse(timeStr, out time))
            {
                return FromHMM(time);
            }
            else
                return default(Time);
        }
        public static Time FromHMM(int time)
        {
            int h = time / 100;
            int m = time - h * 100;
            return new Time(h, m);
        }
        public static Time FromHMM(uint time)
        {
            return FromHMM((uint)time);
        }


        public static int ToHMM(DateTime dateTime)
        {
            return dateTime.Hour * 100 + dateTime.Minute;
        }
        public static int ToHMMSS(DateTime dateTime)
        {
            return dateTime.Hour * 10000 + dateTime.Minute * 100 + dateTime.Second;
        }
        public static Time FromHMMss(string timeStr)
        {
            int time;
            if (int.TryParse(timeStr, out time))
            {
                return FromHMMss(time);
            }
            else
                return default(Time);
        }
        public static Time FromHMMss(int time)
        {
            int h = time / 10000;
            int m = (time - h * 10000) / 100;
            int s = time - h * 10000 - m * 100;
            return new Time(h, m, s);
        }
        public static Time FromHMMss(uint time)
        {
            return FromHMMss((int)time);
        }

        public static Time FromIntAuto(int time)
        {
            if (time > 9999)
                return FromHMMss(time);
            else
                return FromHMM(time);
        }

        public static bool TryParse(string timeStr, out Time time)
        {
            if (string.IsNullOrEmpty(timeStr))
            {
                time = default(Time);
                return false;
            }
            var match = Regex.Match(timeStr, pattern);
            if (match.Success)
            {
                time = new Time(int.Parse(match.Groups[1].Value), int.Parse(match.Groups[2].Value));
                return true;
            }
            else
            {
                time = default(Time);
                return false;
            }
        }
        public static Time Parse(string timeStr)
        {
            Time rtn;
            if (TryParse(timeStr, out rtn))
                return rtn;
            else
            {
                throw new FormatException(string.Format("无法将字符串 {0} 解析为Time类型", timeStr));
            }

        }
        #region 操作符重载
        public static bool operator ==(Time a, Time b)
        {
            return a.Hour == b.Hour && a.Minute == b.Minute && a.Second == b.Second;
        }
        public static bool operator !=(Time a, Time b)
        {

            return !(a == b);
        }
        public static bool operator >(Time a, Time b)
        {
            return a.ToHMMss() > b.ToHMMss();
        }
        public static bool operator <(Time a, Time b)
        {
            return a.ToHMMss() < b.ToHMMss();
        }
        public static bool operator >=(Time a, Time b)
        {
            return a.ToHMMss() >= b.ToHMMss();
        }
        public static bool operator <=(Time a, Time b)
        {
            return a.ToHMMss() <= b.ToHMMss();
        }
        #endregion


        public int CompareTo(object other)
        {
            Time dt = (Time)other;
            return CompareTo(dt);
        }

        public int CompareTo(Time other)
        {
            return this.ToHMMss() - other.ToHMMss();
        }
    }
}
